var _vec3f = require('core/glm.js').vec3f;

var _ButtonIds = require('event/buttonid.js');
var BUTTON_DOWN = _ButtonIds.BUTTON_DOWN;
var BUTTON_UP = _ButtonIds.BUTTON_UP;
var BUTTON_MOVE = _ButtonIds.BUTTON_MOVE;
var BUTTON_CANCEL = _ButtonIds.BUTTON_CANCEL;

var _Constance = require('./constance.js');
var TWEEN = require('third_party/tweenjs/tween.js');

// ==========================
// TouchDelegate
// ==========================
/**
 * @param menu main view
 * @param view slideview
 * @param piece first piece
 * @constructor
 */
function TouchDelegate(menu, view, piece) {
    this.mLocal = _Constance.getLocal();
    this.mLocal.add('touch.slideview', this);

    this.mView = view;
    this.mMenu = menu;

    this.mDistance = piece ? piece.getStart() : 240;
    this.mDownVector = new _vec3f();
    this.mStatus = this.mView.createStatus();
    this.mView.moveTo(this.mDistance, this.mStatus);

    this.absorb = 0;
    this.mAnima = null;
    this.mPreviousPiece = piece;
    this.mNextPiece = piece;

    if (piece) {
        this.mPiece = piece.getId();
    } else {
        this.mPiece = '';
    }
}
TouchDelegate.prototype.toString = function () {
    return '[TouchDelegate]'
};
TouchDelegate.prototype.absorbComplete = function () {
    this.mAnima = null;
    var vertical = this.mLocal.find('touch.delegates');// look for delegates container
    if (vertical) {
        vertical.pieceChange(this.mNextPiece);
    }
};
TouchDelegate.prototype.updateAbsorb = function () {
    this.mView.moveTo(this.absorb, this.mStatus);
};
TouchDelegate.prototype.showTitle = function () {
    var piece = this.mStatus.getPiece();
    var id = piece.getId();
    if (id != this.mPiece) {
        this.mPiece = id;
        this.mMenu.showTitle(piece);
    }
};
TouchDelegate.prototype.moveView = function (dis) {
    this.mView.moveTo(dis, this.mStatus);
};
// ---------------- touch methods
TouchDelegate.prototype.startTouch = function (event) {
    if (this.mAnima) {
        this.mAnima.stop();
        this.mAnima = null;
    }

    this.mDownTime = event.time;
    this.mDistance = this.mView.getDistance();
    this.mDownVector.set(event.vector);
};
TouchDelegate.prototype.moveTouch = function (event) {
    var move = event.vector[0] - this.mDownVector[0];
    this.moveView(this.mDistance - move);
};
TouchDelegate.prototype.endTouch = function (event) {
    var move = event.vector[0] - this.mDownVector[0];
    var dis = this.mDistance - move;

    this.mPreviousPiece = this.mView.currentPiece();

    // if user flip the screen
    //console.log('TouchDelegate.prototype.endTouch');
    //console.log(event.time - this.mDownTime);
    //console.log(move);

    var absmove = Math.abs(move);
    var time = event.time - this.mDownTime;
    if (time <= 0) {
        time = 1;
    }
    while (true) {
        if (absmove > 40) {
            if (absmove / time > 0.15 || absmove > 60) {
                this.mView.getNextPiece(dis, move > 0 ? -1 : 1, this.mStatus);
                break;
            }
        } else if (absmove > 20 && absmove / time > 0.2) {
            this.mView.getNextPiece(dis, move > 0 ? -1 : 1, this.mStatus);
            break;
        }

        this.mView.stopMove(dis, this.mStatus);
        break;
    }

    var target = this.mStatus.getDistance();
    this.mNextPiece = this.mStatus.getPiece();

    // start absorb
    if (this.mAnima) {
        this.mAnima.stop();
    }

    // move to target directly
    var range = Math.abs(target - dis);
    if (range < 6) {
        this.moveView(target);
        this.absorbComplete();
        return;
    }

    // show menu of next piece
    this.showTitle();

    // move with an animation
    var rangealter = range < 50 ? 50 : range;// if distance is to small
    this.absorb = dis;
    var anima = new TWEEN.Tween(this)
        .to({absorb: target}, rangealter / 600)
        .onUpdate(this.updateAbsorb)
        .onComplete(this.absorbComplete);
    if (range >= 80) {// ease when time is long enough
        anima.easing(TWEEN.Easing.Cubic.Out);
    }

    this.mAnima = anima.start();
};
TouchDelegate.prototype.onTouch = function (event) {
    switch (event.state) {
        case BUTTON_DOWN:
            this.startTouch(event);
            break;
        case BUTTON_MOVE:
            this.moveTouch(event);
            break;
        case BUTTON_UP:
        case BUTTON_CANCEL:
            this.endTouch(event);
            break;
    }
    return false;
};

module.exports = TouchDelegate;